<?php declare(strict_types=1);

/**
 * @author      guosir
 * @copyright   2023-2025 owner
 **/

namespace Srv\Apps\Apis\Banner\Ctl;

use Srv\Apps\Apis\Common\Ctl\StorageCtl;
use Srv\Apps\Apis\Common\DefCtl\DefStorageCategoryCtl;
use Srv\Apps\Apis\Develop\Ctl\GlobalConfCtl;
use Srv\Apps\Apis\Skit\Ctl\SkitInfoCtl;
use Srv\Apps\Apis\Skit\Ctl\SkitSeriesCtl;
use Srv\Apps\Proto\DTO\Banner\BannerAddDTO;
use Srv\Apps\Proto\DTO\Banner\BannerEditDTO;
use Srv\Apps\Proto\DTO\Banner\BannerListDTO;
use Srv\Apps\Proto\Enum\BannerOpenTypeEnum;
use Srv\Apps\Proto\Enum\BannerShowStyleEnum;
use Srv\Apps\Proto\Enum\PlatformEnum;
use Srv\Apps\Proto\Enum\YesOrNoEnum;
use Srv\Apps\Proto\VO\Banner\BannerListVO;
use Srv\Apps\Proto\VO\Banner\BannerVO;
use Srv\Apps\Proto\VO\Skit\SkitInfoVO;
use Srv\Apps\Proto\VO\Skit\SkitSeriesVO;
use Srv\Libs\Common\CommArray;
use Srv\Libs\Common\CommTime;
use Srv\Libs\Frame\AuthData;
use Srv\Libs\Frame\ControllerAbstract;
use Srv\Libs\Frame\Page;
use Srv\Libs\Storage\DataMysql;

final class BannerCtl extends ControllerAbstract
{
    private ?DataMysql $DbAuto              = null;     // DB-Write

    /**
     * @return static
     * tag
     */
    final public static function tag():self
    {
        $thisObject                         = self::tagGet();
        if($thisObject instanceof self){
            $thisObject->DbAuto             = self::getDbAuto();
        }
        return $thisObject;
    }

    /**
     * @param int $banrId
     * @return array
     * getBannerSrc
     */
    public function getBannerSrc(int $banrId):array
    {
        if($banrId < 1) return [];
        $isFail             = false;
        $bannerRecord       = $this->DbAuto->getDataOne('SELECT banr_id, banr_platform, banr_title, banr_image, banr_image_two, banr_url, banr_open_type, skio_id, skss_id, banr_hide_nav_bar, banr_status, banr_sort, banr_create_time, banr_update_time FROM '.$this->DbAuto->getTableNameAll('banner_record').' WHERE banr_id='.$banrId.' AND banr_delete=0', $isFail);
        if($isFail || !isset($bannerRecord['banr_id'])) return [];
        return $bannerRecord;
    }

    /**
     * @param Page $Page
     * @param array $whereData
     * @return BannerListVO|null
     * getBannerList
     */
    public function getBannerList(Page $Page, array $whereData): ?BannerListVO
    {
        $limitString        = $Page->getLimitString();
        $whereString        = ' WHERE banr_delete=0 ';
        // 检索条件
        if(count($whereData) > 0)foreach ($whereData as $key => $val){
            switch ($key){
                case BannerListDTO::_banrId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'banr_id='. intval($val);
                    break;
                case BannerListDTO::_title:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'banr_title LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case BannerListDTO::_openType:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'banr_open_type='. intval($val);
                    break;
                case BannerListDTO::_hideNavBar:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'banr_hide_nav_bar='. intval($val);
                    break;
                case BannerListDTO::_status:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'banr_status='. intval($val);
                    break;
                case BannerListDTO::_skioId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'skio_id='. intval($val);
                    break;
                case BannerListDTO::_platform:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'banr_platform='. intval($val);
                    break;
            }
        }
        $isFail             = false;
        $sql                = 'SELECT SQL_CALC_FOUND_ROWS banr_id, banr_platform, banr_title, banr_image, banr_image_two, banr_url, banr_open_type, skio_id, skss_id, banr_hide_nav_bar, banr_status, banr_sort, banr_create_time, banr_update_time FROM '.$this->DbAuto->getTableNameAll('banner_record').$whereString.' ORDER BY banr_id DESC '.$limitString;
        $list               = $this->DbAuto->getData($sql, $isFail);
        $totalNum           = $this->DbAuto->getDataInt('SELECT FOUND_ROWS() as num', 'num');
        if($isFail) return null;
        $BannerVOList       = [];
        if(CommArray::isForeach($list)){
            $skioIdList         = array_map('intval', array_column($list, 'skio_id'));
            $SkitInfoVOList     = SkitInfoCtl::tag()->getSkitInfoBatch($skioIdList);
            $skssIdList         = array_map('intval', array_column($list, 'skss_id'));
            $SkitSeriesVOList   = SkitSeriesCtl::tag()->getSkitSeriesInfoBatch($skssIdList);
            foreach($list as $item){
                $banrIdItem     = intval($item['banr_id']);
                if($banrIdItem < 1) continue;
                $BannerVO       = $this->getBannerVO($item);
                if(!($BannerVO instanceof BannerVO)) continue;
                $SkitInfoVO     = $SkitInfoVOList[intval($item['skio_id'])]??null;
                if($SkitInfoVO instanceof SkitInfoVO) $BannerVO->setSkitInfo($SkitInfoVO);
                $SkitSeriesVO   = $SkitSeriesVOList[intval($item['skss_id'])]??null;
                if($SkitSeriesVO instanceof SkitSeriesVO) $BannerVO->setSeries($SkitSeriesVO);
                $BannerVOList[] = $BannerVO;
            }
        }
        $BannerListVO           = new BannerListVO();
        $BannerListVO->setList($BannerVOList);
        $BannerListVO->setPage($Page->getPageVO($totalNum));
        return $BannerListVO;
    }

    /**
     * @param int $banrId
     * @return BannerVO|null
     * getBannerInfo
     */
    public function getBannerInfo(int $banrId):?BannerVO
    {
        $bannerRecord   = $this->getBannerSrc($banrId);
        if(!isset($bannerRecord['banr_id'])) return null;
        return $this->getBannerVO($bannerRecord);
    }

    /**
     * @param array $bannerRecord
     * @return BannerVO|null
     * getBannerVO
     */
    public function getBannerVO(array $bannerRecord): ?BannerVO
    {
        $banrId         = intval($bannerRecord['banr_id']??0);
        if($banrId < 1) return null;
        $BannerVO       = new BannerVO();
        $BannerVO->setBanrId($banrId);
        $BannerVO->setTitle($bannerRecord['banr_title']);
        $BannerVO->setImageUrl(StorageCtl::tag()->getStorageUrl(trim($bannerRecord['banr_image']), true));
        $BannerVO->setImageTwoUrl(StorageCtl::tag()->getStorageUrl(trim($bannerRecord['banr_image_two']), true));
        $BannerVO->setUrl($bannerRecord['banr_url']);
        $BannerVO->setOpenType(BannerOpenTypeEnum::parseValue($bannerRecord['banr_open_type']));
        $BannerVO->setHideNavBar(YesOrNoEnum::parseValue($bannerRecord['banr_hide_nav_bar']));
        $BannerVO->setStatus(YesOrNoEnum::parseValue($bannerRecord['banr_status']));
        $BannerVO->setSort(intval($bannerRecord['banr_sort']));
        $BannerVO->setCreateTime(intval($bannerRecord['banr_create_time']));
        $BannerVO->setUpdateTime(intval($bannerRecord['banr_update_time']));
        $BannerVO->setPlatform(PlatformEnum::parseValue($bannerRecord['banr_platform']));
        return $BannerVO;
    }

    /**
     * @param array $setData
     * @return int
     * bannerAdd
     */
    public function bannerAdd(array $setData):int
    {
        if(count($setData) < 1) return 0;
        $currTime       = CommTime::getTimeStamp();
        $setString      = '';
        $admUserId      = AuthData::getLoginUserId();
        $globalSrc      = GlobalConfCtl::tag()->getGlobalConfSrcByKey(GlobalConfCtl::KEY_APP_BANNER_SHOW_STYLE);
        if(!isset($globalSrc['stgs_value'])) return 0;
        $bannerShowType = BannerShowStyleEnum::parseValue($globalSrc['stgs_value']);
        if($bannerShowType < 1) return 0;
        if($bannerShowType === BannerShowStyleEnum::BANNER_SHOW_STYLE_ONE && !isset($setData[BannerAddDTO::_imageKey])) return 0;
        if($bannerShowType === BannerShowStyleEnum::BANNER_SHOW_STYLE_TWO && !isset($setData[BannerAddDTO::_imageTwoKey])) return 0;
        foreach ($setData as $key => $val){
            switch ($key){
                case BannerAddDTO::_title:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_title=\''.$this->DbAuto->getRealEscapeString($val) .'\'';
                    break;
                case BannerAddDTO::_imageKey:
                    $dsacId         = DefStorageCategoryCtl::tag()->getIdByKey(DefStorageCategoryCtl::KEY_BANNER_APP);
                    if($dsacId < 1) return 0;
                    $saveUrl        = StorageCtl::tag()->getStorageUrlRecord($admUserId, $dsacId, $val);
                    if(strlen($saveUrl) < 1) return 0;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_image=\''.$this->DbAuto->getRealEscapeString($saveUrl) .'\'';
                    break;
                case BannerAddDTO::_imageTwoKey:
                    $dsacId         = DefStorageCategoryCtl::tag()->getIdByKey(DefStorageCategoryCtl::KEY_BANNER_APP);
                    if($dsacId < 1) return 0;
                    $saveUrl        = StorageCtl::tag()->getStorageUrlRecord($admUserId, $dsacId, $val);
                    if(strlen($saveUrl) < 1) return 0;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_image_two=\''.$this->DbAuto->getRealEscapeString($saveUrl) .'\'';
                    break;
                case BannerAddDTO::_url:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_url=\''.$this->DbAuto->getRealEscapeString($val) .'\'';
                    break;
                case BannerAddDTO::_openType:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_open_type='.intval($val);
                    break;
                case BannerAddDTO::_skioId:
                    $skioId         = intval($val);
                    $skitInfoSrc    = SkitInfoCtl::tag()->getSkitInfoSrc($skioId);
                    if(!isset($skitInfoSrc['skio_id']) && $setData[BannerEditDTO::_openType] === BannerOpenTypeEnum::BANNER_OPEN_TYPE_SKIT) return 0;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'skio_id='.$skioId;
                    break;
                case BannerAddDTO::_skssId:
                    $skssId         = intval($val);
                    if($skssId > 0){
                        $seriesSrc  = SkitSeriesCtl::tag()->getSkitSeriesSrc($skssId);
                        if(!isset($seriesSrc['skss_id'])) return 0;
                    }
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'skss_id='.$skssId;
                    break;
                case BannerAddDTO::_hideNavBar:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_hide_nav_bar='.intval($val);
                    break;
                case BannerAddDTO::_status:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_status='.intval($val);
                    break;
                case BannerAddDTO::_sort:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_sort='.intval($val);
                    break;
                case BannerAddDTO::_platform:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_platform='.intval($val);
                    break;
            }
        }
        if(strlen($setString) < 1) return 0;
        $isFail     = false;
        $sql        = 'INSERT INTO '.$this->DbAuto->getTableNameAll('banner_record').' SET '.$setString.', banr_create_time='.$currTime.', banr_update_time='.$currTime;
        $banrId     = $this->DbAuto->getDataId($sql, $isFail);
        if($isFail || $banrId < 1) return 0;
        return $banrId;
    }

    /**
     * @param int $banrId
     * @param array $setData
     * @return bool
     * bannerEdit
     */
    public function bannerEdit(int $banrId, array $setData):bool
    {
        if($banrId < 1 || count($setData) < 1) return false;
        $currTime       = CommTime::getTimeStamp();
        $admUserId      = AuthData::getLoginUserId();
        $setString      = '';
        foreach ($setData as $key => $val){
            switch ($key){
                case BannerEditDTO::_title:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_title=\''.$this->DbAuto->getRealEscapeString($val) .'\'';
                    break;
                case BannerEditDTO::_imageKey:
                    $dsacId         = DefStorageCategoryCtl::tag()->getIdByKey(DefStorageCategoryCtl::KEY_BANNER_APP);
                    if($dsacId < 1) return false;
                    $saveUrl        = StorageCtl::tag()->getStorageUrlRecord($admUserId, $dsacId, $val);
                    if(strlen($saveUrl) < 1) return false;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_image=\''.$this->DbAuto->getRealEscapeString($saveUrl) .'\'';
                    break;
                case BannerEditDTO::_imageTwoKey:
                    $dsacId         = DefStorageCategoryCtl::tag()->getIdByKey(DefStorageCategoryCtl::KEY_BANNER_APP);
                    if($dsacId < 1) return false;
                    $saveUrl        = StorageCtl::tag()->getStorageUrlRecord($admUserId, $dsacId, $val);
                    if(strlen($saveUrl) < 1) return false;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_image_two=\''.$this->DbAuto->getRealEscapeString($saveUrl) .'\'';
                    break;
                case BannerEditDTO::_url:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_url=\''.$this->DbAuto->getRealEscapeString($val) .'\'';
                    break;
                case BannerEditDTO::_openType:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_open_type='.intval($val);
                    break;
                case BannerEditDTO::_skioId:
                    $skioId         = intval($val);
                    $skitInfoSrc    = SkitInfoCtl::tag()->getSkitInfoSrc($skioId);
                    if(!isset($skitInfoSrc['skio_id']) && $setData[BannerEditDTO::_openType] === BannerOpenTypeEnum::BANNER_OPEN_TYPE_SKIT) return false;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'skio_id='.$skioId;
                    break;
                case BannerEditDTO::_skssId:
                    $skssId         = intval($val);
                    if($skssId > 0){
                        $seriesSrc  = SkitSeriesCtl::tag()->getSkitSeriesSrc($skssId);
                        if(!isset($seriesSrc['skss_id'])) return false;
                    }
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'skss_id='.$skssId;
                    break;
                case BannerEditDTO::_hideNavBar:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_hide_nav_bar='.intval($val);
                    break;
                case BannerEditDTO::_status:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_status='.intval($val);
                    break;
                case BannerEditDTO::_sort:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_sort='.intval($val);
                    break;
                case BannerEditDTO::_platform:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'banr_platform='.intval($val);
                    break;
            }
        }
        if(strlen($setString) < 1) return false;
        $isFail     = false;
        $sql        = 'UPDATE '.$this->DbAuto->getTableNameAll('banner_record').' SET '.$setString.', banr_update_time='.$currTime.' WHERE banr_id='.$banrId.' AND banr_delete=0';
        $this->DbAuto->getDataNum($sql, $isFail);
        if($isFail) return false;
        return true;
    }
}